/*  PLUTO JS -Scripting Web Server.
    Copyright (C) 2013 vivek gangadharan

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package pluto.core;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;

public class Util {

    @SuppressWarnings("empty-statement")
    public static void shutdownService(ExecutorService service) {
        if (service == null) {
            return;
        }
        service.shutdown(); 
        try {
            if (!service.awaitTermination(60, TimeUnit.SECONDS)) {
                service.shutdownNow();
                if (!service.awaitTermination(60, TimeUnit.SECONDS)) {
                    ;
                }
            }
        } catch (InterruptedException ie) {
            service.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

    public static ServerSocket http(InetAddress inetaddress, int port, int backlog) throws UnknownHostException, IOException {
        return new ServerSocket(port, backlog, inetaddress);
    }

    public static ServerSocket https(InetAddress inetaddress, int port, int backlog, File keystore, char[] storePassword, char[] keyPassword, String keyManagerType) throws UnknownHostException, IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, KeyManagementException {
        SSLContext context = getSSLContext(keystore, storePassword, keyPassword, keyManagerType);
        SSLServerSocketFactory factory = context.getServerSocketFactory();
        SSLServerSocket ss = (SSLServerSocket) (factory.createServerSocket(port, backlog, inetaddress));
        ss.setEnableSessionCreation(true);
        ss.setWantClientAuth(true);
        return ss;
    }

    public static SSLContext getSSLContext(File keyStoreName, char[] storePassword, char[] keyPassword, String keyManagerType)
            throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, KeyManagementException {
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(keyManagerType);
        InputStream in = new FileInputStream(keyStoreName);
        KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(in, storePassword);
        kmf.init(ks, keyPassword);
        for (Enumeration e = ks.aliases(); e.hasMoreElements();) {
            String alias = (String) e.nextElement();
        }

        SSLContext context = SSLContext.getInstance("SSL");
        context.init(kmf.getKeyManagers(), null, null);
        if (storePassword != null) {
            Arrays.fill(storePassword, 'x');
        }
        if (keyPassword != null) {
            Arrays.fill(keyPassword, 'x');
        }
        return context;
    }
}
